package net.dgg.zz.common.service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import net.dgg.framework.tac.mq.rabbitmq.queue.DggMessageSendUtil;
import net.dgg.iboss.base.service.CmsService;
import net.dgg.iboss.base.service.OrfApiService;
import net.dgg.tmd.foundation.platform.org.entity.OrganizationDTO;
import net.dgg.tmd.foundation.platform.org.service.OrganizationManager;
import net.dgg.tmd.foundation.platform.session.SessionManager;
import net.dgg.tmd.foundation.platform.treebook.service.TreeBookService;
import net.dgg.tmd.foundation.platform.user.entity.UserDTO;
import net.dgg.tmd.foundation.platform.user.entity.UserEntity;
import net.dgg.tmd.foundation.platform.user.service.UserService;
import net.dgg.zz.common.base.service.BaseService;
import net.dgg.zz.common.constant.ScProductConstant;
import net.dgg.zz.common.constant.SystemCommonConstant;
import net.dgg.zz.common.entity.PlaceCodeArea;
import net.dgg.zz.common.excption.CommonExcption;
import net.dgg.zz.common.utils.MQMessageSendUtil;
import net.dgg.zz.common.utils.StringUtils;
import net.dgg.zz.common.utils.ValidateUtils;
import net.dgg.zz.credential.excption.CertificateExcption;
import net.dgg.zz.production.chargeback.dao.ZzProductOrderDao;
import net.dgg.zz.production.entity.ProductOrder;
import net.dgg.zz.production.inProcess.service.ZzInProcessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 公用Service
 */
@Service
public class CommonService extends BaseService {
    @Resource
    private TreeBookService treeBookService;
    @Resource
    private UserService usersService;
    @Autowired
    private SessionManager sessionManager;
    @Autowired
    private OrganizationManager organizationManager;
    @Autowired
    private CmsService cmsService;
    @Autowired
    private ZzProductOrderDao zzProductOrderDao;
    @Autowired
    private ZzInProcessService zzInProcessService;
    @Autowired
    private OrfApiService orfApiService;

    /**
     * 查询字典接口
     *
     * @param code   编码
     * @param status 状态 1：启用，0：禁用，无：所有
     * @param type   1：根据分类编码查询下级第一级分类（用于Select选择）
     *               2：根据分类编码查询所有下级分类（用于Tree选择无父级的）
     *               3：根据分类编码查询所有下级分类包含自己（用于Tree选择有父级的）
     * @return
     */
    public List<Map> queryTreeBook(String code, Integer status, Integer type, Integer level) {
        List<Map> treeBooks = cmsService.getTreeBookList(code, status, type, level);
        return treeBooks;
    }


    /**
     * 用户息查询
     *
     * @param params
     * @return
     */
    public List<UserDTO> findUserDTOList(Map params) {
        // 用户信息选择类型
        String type = "all";// 默认:全部用户，division：当前登录人所在事业部，department:当前登录人所在部门及以下
        if (StringUtils.isNotEmpty(params.get("type"))) {
            type = params.get("type").toString();
        }
        if ("division".equals(type)) {
            UserEntity userEntity = sessionManager.getCurrentUser();
            OrganizationDTO organ = organizationManager.findOrgParentByLevel(userEntity.getOrgId(), "ORG_LEVEL_1");
            if (null != organ) {
                List<Long> listIds = organizationManager.findOrgIdsByPId(organ.getId());
                params.put("orgIds", listIds);
            }
        } else if ("department".equals(type)) {
            UserEntity userEntity = sessionManager.getCurrentUser();
            List<Long> listIds = organizationManager.findOrgIdsByPId(userEntity.getOrgId());
            params.put("orgIds", listIds);
        } else if ("role".equals(type)) {
            if (StringUtils.isNotEmpty(params.get("roleCode"))) {
                List<Long> userIds = usersService.findUserByRoleCode(params.get("roleCode").toString());
                params.put("userIds", userIds);
            }
        }
        if (StringUtils.isNotEmpty(params.get("roleName"))) {
            List<Long> userIds = usersService.findUserByRoleCode(params.get("roleName").toString());
            params.put("userIds", userIds);
        }
        // 判断是否选择了部门查询条件
        if (StringUtils.isNotEmpty(params.get("organId"))) {
            Long organId = Long.parseLong(params.get("organId").toString());
            List<Long> listIds = organizationManager.findOrgIdsByPId(organId);
            if (null != listIds && listIds.size() > 0) {
                params.put("orgIds", listIds);
            }
        }
        // 判断是否分页查询
        if (StringUtils.isNotEmpty(params.get("length")) && StringUtils.isNotEmpty(params.get("start"))) {
            Integer count = usersService.findUserCount(params);
            params.put("count", count);
            Integer limit = Integer.parseInt(params.get("length").toString());
            Integer start = Integer.parseInt(params.get("start").toString());
            params.put("limit", limit);
            params.put("start", start);
        }

        List<UserDTO> userList = usersService.findUserDTOPage(params);
        return userList;
    }

    /**
     * 查询用户所在事业部
     *
     * @param user
     * @return
     */
    public Long findUserSyb(UserEntity user) {
        Long sybId = organizationManager.findOrgParentIdByIdAndOrgLevel(user.getOrgId(), "ORG_LEVEL_1");
        ValidateUtils.isTrue(StringUtils.isNotEmpty(sybId), CommonExcption.class, "该用户组织机构没有所在事业部");
        return sybId;
    }

    /**
     * 查询用户所在事业部的区域
     *
     * @param user
     * @return
     */
    public String findUserArea(UserEntity user) {
        OrganizationDTO organ = organizationManager.findOrgParentByLevel(user.getOrgId(), "ORG_LEVEL_1");
        ValidateUtils.isTrue(StringUtils.isNotEmpty(organ), CommonExcption.class, "该用户组织机构没有所在事业部");
        return organ.getPlaceCode();
    }

    /**
     * 查询事业部的区域
     *
     * @param orgId
     * @return
     */
    public String findOrgArea(Long orgId) {
        OrganizationDTO organ = organizationManager.findOrgParentByLevel(orgId, "ORG_LEVEL_1");
        ValidateUtils.isTrue(StringUtils.isNotEmpty(organ), CommonExcption.class, "该用户组织机构没有所在事业部");
        return organ.getPlaceCode();
    }

    /**
     * 根据条件查询所有部门
     *
     * @param params ｛
     *               type: 部门查询类型
     *               all:全部部门，division：当前登录人所在事业部下所有部门，department:当前登录人所在部门下所有部门
     *               ｝
     * @return
     */
    public List<Map<String, Object>> findParamsOrgan(Map params) {
        Long organId = 1L;
        String type = "all";// all:全部部门，division：当前登录人所在事业部下所有部门，department:当前登录人所在部门下所有部门
        if (StringUtils.isNotEmpty(params.get("type"))) {
            type = params.get("type").toString();
        }
        if ("division".equals(type)) {
            UserEntity userEntity = sessionManager.getCurrentUser();
            OrganizationDTO organ = organizationManager.findOrgParentByLevel(userEntity.getOrgId(), "ORG_LEVEL_1");
            if (null != organ){
                organId = organ.getId();
            }
        } else if ("department".equals(type)) {
            UserEntity userEntity = sessionManager.getCurrentUser();
            organId = userEntity.getOrgId();
        }
        params.put("orgId", organId);
        params.put("enabled", 1);
        params.remove("type");
        List<OrganizationDTO> organList = organizationManager.findOrgChlidsPage(params);
        List<Map<String, Object>> list = new ArrayList<>();
        for (OrganizationDTO org : organList) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", org.getId());
            map.put("name", org.getName());
            map.put("parentId", org.getpId());
            list.add(map);
        }
        return list;
    }

    //根据生产订单id修改生产订单状态证书为完结
    @Transactional
    public void updateScProductOrderStatus(Long id) {
        UserEntity userEntity = sessionManager.getCurrentUser();
        Assert.notNull(userEntity, "未获取到登陆人，请重新登录！");
        Assert.notNull(id, "生产订单ID不能为空！");
        ProductOrder scProductOrder = this.zzProductOrderDao.getById(Long.valueOf(id));
        Assert.notNull(scProductOrder, "未查询到此生产订单，请刷新列表！");
        Assert.isTrue(!scProductOrder.getStatus().equals(ScProductConstant.SC_ORDER_OVER_CERTIFICATE), "该生产订单已经完结，请刷新列表！");
        scProductOrder.setStatus(ScProductConstant.SC_ORDER_OVER_CERTIFICATE); //证书完结
        zzProductOrderDao.update(scProductOrder);


        //子订单完结调用子订单完结接口
        zzInProcessService.updateOrderBusiness(scProductOrder, userEntity, "ORF_BDZT_1");
        //判断生产子订单是否全部证书完结
        Integer status = 1;
        List<ProductOrder> scProductOrderList = zzProductOrderDao.query(new HashMap() {{
            put("orderId", scProductOrder.getOrderId());
        }});
        for (ProductOrder productOrder : scProductOrderList) {
            if (productOrder.getId().equals(scProductOrder.getId())) { //去除本次修改的
                continue;
            }
            if (!(productOrder.getStatus().equals(ScProductConstant.SC_ORDER_JUNCTIONS))
                    && !(productOrder.getStatus().equals(ScProductConstant.SC_ORDER_OVER_CERTIFICATE))) { //不是结项和证书完结的
                status++;
            }
        }
        //证明全部已经完结
//        if (status == 1) {
//            //调同步接口
//            orfApiService.updateOrder(scProductOrder.getOrderId(), userEntity.getId(), "ORF_DDZT_6", null);
//        }
        //提交之后，将订单信息同步到企大顺生产中心
        MQMessageSendUtil.qdsMessageSend(scProductOrder, null,  userEntity);
    }

    /*
     * @Author zsx
     * @Date 2018-09-03 11:09:13
     * @Description  查询资质审核拥有权限的人
     * @param roleCode 权限code
     * @return  List<UserDTO>
     */
    public Set<UserEntity> findUserByOrgAndRole() {
        UserEntity userEntity = sessionManager.getCurrentUser();
        OrganizationDTO organ = organizationManager.findOrgParentByLevel(userEntity.getOrgId(), "ORG_LEVEL_1");
        ValidateUtils.strNotEmpty(organ, CertificateExcption.class, "当前登录人未查询到组织架构");
        List<Long> orgIds = organizationManager.findOrgIdByAncestorId(organ.getId());
        orgIds.add(organ.getId());
        Set<UserEntity> users = new HashSet<>();
        users.addAll(usersService.findUserByOrgAndRole(orgIds, "ZZSC_ZZ_ADMIN"));
        users.addAll(usersService.findUserByOrgAndRole(orgIds, "ZZSC_ZZ_SUPER_ADMIN"));
        return users;
    }

    /**
     * 翻译指定code
     *
     * @param codes
     * @return
     */
    public List<Map> getTreeBookObjMulti(String codes) {
        return cmsService.getTreeBookObjMulti(codes);
    }


    /**
     * 2018年6月14日 16:30:09
     * 修改  先计算预计完结时间 再按自然日 顺延 暂停总时长
     *
     * @param start
     * @param len
     * @param suspendMiniSec
     * @return
     */
    public Date getWorkDateFrom(Date start, Integer len, Long suspendMiniSec) {
        Date date = this.getWorkDateFrom(start, len);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
//        calendar.add(Calendar.MILLISECOND, suspendMiniSec.intValue());
        return calendar.getTime();
    }

    /**
     * 获取从某日开始x个工作日的日期
     *
     * @param start 开始日期
     * @param len   天数
     * @return
     */
    public Date getWorkDateFrom(Date start, Integer len) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendarStart = Calendar.getInstance();
        calendarStart.setTime(start);
        Map map = new HashMap();
        map.put("date", fmt.format(start));
        map.put("days", len);
        String dateStr = this.cmsService.findAfterDate(fmt.format(start), len);
        Assert.hasText(dateStr, "获取工作日失败！");
        Date date = null;
        try {
            date = fmt.parse(dateStr);
            Calendar calendar1 = Calendar.getInstance();
            calendar1.setTime(date);
            calendar1.set(Calendar.HOUR_OF_DAY, calendarStart.get(Calendar.HOUR_OF_DAY));
            calendar1.set(Calendar.MINUTE, calendarStart.get(Calendar.MINUTE));
            calendar1.set(Calendar.SECOND, calendarStart.get(Calendar.SECOND));
            calendar1.set(Calendar.MILLISECOND, calendarStart.get(Calendar.MILLISECOND));
            return calendar1.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            Assert.isTrue(false, "工作日期转换出现异常！");
        }
        return date;
    }


    /**
     * 获取代入暂停时间后的 从某日开始x个工作日的日期
     *
     * @param start          开始日期
     * @param len            天数
     * @param suspendMiniSec 暂停时长 单位: 毫秒
     * @return
     */
    private Date getDateFrom(Date start, Integer len, Long suspendMiniSec) {
        Calendar calendarStart = Calendar.getInstance();
        calendarStart.setTime(start);
        Calendar overCalendar = Calendar.getInstance();
        overCalendar.setTime(start);
        overCalendar.add(Calendar.DAY_OF_YEAR, len);
//        overCalendar.add(Calendar.MILLISECOND, suspendMiniSec.intValue());
        return overCalendar.getTime();
    }

    /**
     * 计算日期 存在暂停时间时
     *
     * @param start          开始时间
     * @param len            天数
     * @param suspendMiniSec 暂停时长 ：毫秒
     * @param dateType       类型，常量定义于 WorkDayOrNaturalDayStatus
     * @return
     */
    public Date getDateFromStartByType(Date start, Integer len, Long suspendMiniSec, int dateType) {
        return ScProductConstant.WORKDAY_STATUS == dateType ?
                this.getWorkDateFrom(start, len, suspendMiniSec) : this.getDateFrom(start, len, suspendMiniSec);
    }
    /**
     * 获取从某日开始x个小时的日期
     *
     * @param start 开始日期
     * @param len   天数
     * @return
     */
    public Date getWorkDateFromHour(Date start, Integer len) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = this.cmsService.findAfterTime(fmt.format(start), len);
        Assert.hasText(dateStr, "获取工作日失败！");
        Date date = null;
        try {
            date = fmt.parse(dateStr);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
            Assert.isTrue(false, "工作日期转换出现异常！");
        }
        return date;
    }
    /**
     * 获取从某日开始x个自然日的小时
     *
     * @param start 开始日期
     * @param len   天数
     * @return
     */
    public Date getDateFromHour(Date start, Integer len) {
        Calendar overCalendar = Calendar.getInstance();
        overCalendar.setTime(start);
        overCalendar.add(Calendar.HOUR_OF_DAY,len);
        return overCalendar.getTime();
    }


    /**
     * 翻译城市代码
     *
     * @param code
     * @return
     */
    public String translateCityCode(@RequestParam String code) {
        String codes = "";
        Map treeBookObj = cmsService.getTreeBookObj(code);

        // 如果上级不包含全国
        if (!SystemCommonConstant.NATIONWIDE.equals(treeBookObj.get("pcode"))) {
            Map parentTreeBook = cmsService.getTreeBookObj(treeBookObj.get("pcode").toString());
            codes += parentTreeBook.get("name").toString() + "/";
        }
        codes += treeBookObj.get("name").toString();
        return codes;
    }


    /**
    * <p>@Description 异步推送消息</p>
    * <p>@author mqy</p>
     * @param userEntityList 推送消息的对象
     * @param  msg      消息内容
     * @param  templateCode      消息模板的code
    * <p>@Time 2018/9/14 0014 9:40 创建时间</p>
    * <p>@return</p>
    */
    public void sendMsgByAsynchronous(List<UserEntity>  userEntityList,String[] msg,String templateCode){
        //给他整个名字
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("send-msg-pool-%d").build();
        //核心线程一个,最大四个,五秒回收,多余的排队
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 4,
                5, TimeUnit.SECONDS, new SynchronousQueue<>(),threadFactory);
        //这里使用了 lambda 表达式
        executor.execute(()-> {
                for (UserEntity sendUser : userEntityList) {
                    cmsService.sendMessage(sendUser.getId(), 1L, msg, templateCode, 1);
           }
        });
    }

    /**
     * 返回当天17:00的时间
     * @return
     */
    public Date getDate(){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formatStr =formatter.format(new Date());
        formatStr = formatStr+" 17:00:00";
        try {
            return formatter1.parse(formatStr);
        } catch (ParseException e) {
            e.printStackTrace();
            return new Date();
        }
    }

    /**
     * 返回当天23点59分59秒
     * @return
     */
    public Date getNowEndDate(){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formatStr =formatter.format(new Date());
        formatStr = formatStr+" 23:59:59";
        try {
            return formatter1.parse(formatStr);
        } catch (ParseException e) {
            e.printStackTrace();
            return new Date();
        }

    }

    /**
     * 发送企管家消息
     * @param orderId
     * @param userId
     * @param userName
     * @param loginName
     * @param content
     */
    public void sendQgjMessage(Long orderId,String businessTypeId,Long userId,String userName,String loginName,String content){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderId",orderId);
        jsonObject.put("businessTypeId",businessTypeId);
        jsonObject.put("content",content);
        jsonObject.put("userId",userId);
        jsonObject.put("userName",userName);
        jsonObject.put("loginName",loginName);
        DggMessageSendUtil.putMessage("net.dgg.iboss.orf.order2.OrderButlerChangeEvent", jsonObject);
    }
}



